<!DOCTYPE html>
<html lang="en" style="height: 100%">

<head>
    <meta charset="utf-8">
    <title>期货K线图</title>
    <script src="./static/echarts.min.js"></script>

</head>

<body style="height: 100%; margin: 0">
    <div id="container" style="height: 100%"></div>


</body>
<script>
    var dom = document.getElementById('container');
    var myChart = echarts.init(dom, null, {
        renderer: 'canvas',
        useDirtyRect: false
    });
    var app = {};

    var option;

    const upColor = '#ec0000';
    const upBorderColor = '#8A0000';
    const downColor = '#00da3c';
    const downBorderColor = '#008F28';
    const dataCount = 100;
    const data = generateOHLC(dataCount)
    /*
    二维数组，每个data[i]是一条数据
    data[0]=["2025-03-03\n09:29:15",5853,5853,5853,5853,129,1,1212,1232]，可以在其中添加其他数据 ，使用时在下面指定坐标
    encode: {
                     x: 0,           // x轴使用的数据(data[i][0]),二维数组的第0列
                     y: 4           // y轴使用的数据(data[i][4]),二维数组的第4列
                 }
    */
    console.log(data)
    option = {
        // 数据集配置
        dataset: {
            source: data  // 数据源，使用前面定义的data变量，在后面的series中使用
        },
        // 标题配置
        title: {
            text: '数据量: ' + echarts.format.addCommas(data.length)  // 显示总数据量，并添加千位分隔符
        },
        legend: {// 图例配置
            data: ['额外数据1', '额外数据2']// 图例数据数组，与series中各个图的name字段对应，可以实现显示和隐藏图
        },
        // 提示框配置
        tooltip: {
            trigger: 'axis',  // 触发类型，坐标轴触发
            axisPointer: {
                type: 'line'  // 指示器类型为直线
            }
        },
        // 工具箱配置
        toolbox: {
            feature: {
                dataZoom: {  // 数据区域缩放
                    yAxisIndex: false  // 不关联y轴
                }
            }
        },
        // 网格配置，可以设置多个网格用于放置不同的图表
        grid: [
            {
                left: '10%',    // 左边距10%
                right: '10%',  // 右边距10%
                bottom: 200    // 底部距离200px（为下面的成交量图留空间）
            },
            {
                left: '10%',   // 左边距10%
                right: '10%',   // 右边距10%
                height: 80,     // 高度80px
                bottom: 80      // 底部距离80px
            }
            // 如果要添加多轴，可以在这里继续添加新的grid配置
            // 也可以不配置，而是堆叠到同一张图中？
        ],
        // X轴配置
        xAxis: [
            {//这里没有指定gridIndex，推测其默认值为0
                type: 'category',      // 类目轴
                boundaryGap: false,    // 坐标轴两边不留白
                axisLine: { onZero: false },  // 坐标轴线不在零刻度上
                splitLine: { show: false },    // 不显示分割线
                min: 'dataMin',        // 最小值为数据最小值
                max: 'dataMax'         // 最大值为数据最大值
            },
            {   // 第二个x轴（用于成交量图）
                type: 'category',
                gridIndex: 1,          // 关联到第二个grid
                boundaryGap: false,
                axisLine: { onZero: false },
                axisTick: { show: false },     // 不显示坐标轴刻度
                splitLine: { show: false },    // 不显示分割线
                axisLabel: { show: false },   // 不显示坐标轴标签
                min: 'dataMin',
                max: 'dataMax'
            }
            // 添加更多x轴示例:
            // {
            //     type: 'value',      // 数值型轴
            //     gridIndex: 2,       // 关联到第三个grid
            //     position: 'right'   // 位置在右侧
            // }
            // 添加更多x轴示例:
            , {
                type: 'value',      // 数值型轴
                gridIndex: 0,       // 关联到第0个grid（K线图）
                position: 'right'   // 位置在右侧
            }
            , {

                type: 'value',      // 数值型轴
                gridIndex: 0,       // 关联到第0个grid（K线图）
                position: 'right'   // 位置在右侧
            }
        ],
        // Y轴配置
        yAxis: [
            {//K线图y轴，这里没有指定gridIndex，推测其默认值为0
                axisLine: { onZero: false },
                scale: true,           // 自动缩放
                splitArea: {
                    show: true         // 显示分割区域
                }
            },
            {   // 第二个y轴（用于成交量图）
                axisLine: { onZero: false },
                scale: true,
                gridIndex: 1,         // 关联到第二个grid
                splitNumber: 2,        // 分割段数
                axisLabel: { show: false },    // 不显示坐标轴标签
                axisLine: { show: false },     // 不显示坐标轴线
                axisTick: { show: false },     // 不显示坐标轴刻度
                splitLine: { show: false }    // 不显示分割线
            },
            // 添加更多y轴示例:
            // {
            //     gridIndex: 2,       // 关联到第三个grid
            //     scale: true,
            //     position: 'right',  // 位置在右侧
            //     name: '额外指标'    // 轴名称
            // }
            // 添加更多y轴示例:
            {
                axisLine: { onZero: false },
                gridIndex: 0,       // 关联到第0个grid(K线图)
                scale: true,
                position: 'right',  // 位置在右侧
                name: '额外指标1',   // 轴名称
                offset: 50,//与axisLine:{onZero:false},搭配，参数详情见：https://echarts.apache.org/zh/option.html#yAxis.position
                axisLabel: {
                    rotate: -45,// 标签旋转45度
                    formatter: function (value) {  // 格式化函数，只显示时间部分（假设原始格式为"日期 时间"）
                        //return value/1000;
                        return value;
                    }
                }
            },
            {
                axisLine: { onZero: false },
                gridIndex: 0,       // 关联到第0个grid(K线图)
                scale: true,
                position: 'right',  // 位置在右侧
                name: '额外指标2',    // 轴名称
                offset: 100//与axisLine:{onZero:false},搭配参数详情见：https://echarts.apache.org/zh/option.html#yAxis.position
                , axisLabel: {
                    rotate: 45,// 标签旋转45度
                }
            }
        ],
        // 数据缩放配置
        dataZoom: [
            {
                type: 'inside',      // 内置型数据区域缩放
                xAxisIndex: [0, 1],   // 同时控制第一个和第二个x轴
                start: 10,            // 初始窗口范围的起始百分比
                end: 100              // 初始窗口范围的结束百分比
            },
            {
                show: true,           // 显示滑动条
                xAxisIndex: [0, 1],   // 同时控制第一个和第二个x轴
                type: 'slider',       // 滑动条型数据区域缩放
                bottom: 10,          // 距离容器底部10px
                start: 10,            // 初始窗口范围的起始百分比
                end: 100             // 初始窗口范围的结束百分比
            }
        ],
        // 视觉映射配置
        visualMap: {
            show: false,              // 不显示视觉映射组件
            seriesIndex: 1,          // 作用于第二个series（成交量图）
            dimension: 6,            // 使用数据的第7个维度（sign字段）
            pieces: [                // 定义映射规则
                {
                    value: 1,        // 当值为1时
                    color: upColor   // 使用上涨颜色
                },
                {
                    value: -1,       // 当值为-1时
                    color: downColor // 使用下跌颜色
                }
            ]
        },
        // 系列列表配置
        series: [
            {   // K线图系列,这里没有指定xAxisIndex、yAxisIndex推测默认值是0
                type: 'candlestick',  // 蜡烛图类型
                itemStyle: {          // 图形样式
                    color: upColor,   // 上涨颜色
                    color0: downColor,// 下跌颜色
                    borderColor: upBorderColor,   // 上涨边框颜色
                    borderColor0: downBorderColor // 下跌边框颜色
                },
                encode: {            // 数据编码,dataset.source中data数组的下标
                    x: 0,            // x轴使用第1个维度（时间）
                    y: [1, 4, 3, 2]  // y轴依次使用开盘价、收盘价、最低价、最高价，顺序详情见https://echarts.apache.org/examples/zh/editor.html?c=candlestick-large中的function generateOHLC()函数
                }
            },
            {   // 成交量图系列
                name: 'Volumn',      // 系列名称
                type: 'bar',          // 柱状图类型
                xAxisIndex: 1,       // 使用第二个x轴
                yAxisIndex: 1,       // 使用第二个y轴
                itemStyle: {
                    color: '#7fbe9e'  // 柱状图颜色
                },
                large: true,          // 开启大规模模式优化
                encode: {             // 数据编码,dataset.source中data数组的下标
                    x: 0,            // x轴使用第1个维度（时间）
                    y: 5             // y轴使用第6个维度（成交量）
                }
            }
            // 添加多轴系列示例:
            // {
            //     type: 'line',       // 折线图类型
            //     yAxisIndex: 2,      // 使用第三个y轴
            //     encode: {
            //         x: 0,           // 时间维度
            //         y: 7           // 假设第8个维度是额外指标
            //     }
            // }

            // 添加多轴系列示例:
            , {//对应xAxis、yAxis中的第三个
                name: '额外数据1',//与legend对应，可以出现一个按钮用于显示和隐藏这个图，同时也是提示框中的名字
                type: 'line',       // 折线图类型
                yAxisIndex: 2,      // 使用第三个y轴
                encode: {            //数据编码，dataset.source中data数组的下标
                    x: 0,           // 时间维度
                    y: 7           // 假设第8个维度是额外指标
                }
            }
            , {//对应xAxis、yAxis中的第4个
                name: '额外数据2',
                type: 'line',       // 折线图类型
                yAxisIndex: 3,      // 使用第4个y轴，注意没有指定x轴
                //xAxisIndex: 0,     //没啥效果
                encode: {              //数据编码，dataset.source中data数组的下标
                    x: 0,           // 时间维度
                    y: 8           // 假设第9个维度是额外指标
                }
            }
        ]
    };


    function generateOHLC(count) {//参考官网的产生随机数据的代码https://echarts.apache.org/examples/zh/editor.html?c=candlestick-large
        let data = [];
        let xValue = +new Date(2011, 0, 1);
        let minute = 60 * 1000;
        let baseValue = Math.random() * 12000;
        let boxVals = new Array(4);
        let dayRange = 12;
        for (let i = 0; i < count; i++) {
            baseValue = baseValue + Math.random() * 20 - 10;
            for (let j = 0; j < 4; j++) {
                boxVals[j] = (Math.random() - 0.5) * dayRange + baseValue;
            }
            boxVals.sort();
            let openIdx = Math.round(Math.random() * 3);
            let closeIdx = Math.round(Math.random() * 2);
            if (closeIdx === openIdx) {
                closeIdx++;
            }
            let volumn = boxVals[3] * (1000 + Math.random() * 500);
            // ['open', 'close', 'lowest', 'highest', 'volumn']
            // [1, 4, 3, 2]
            data[i] = [
                echarts.format.formatTime('yyyy-MM-dd\nhh:mm:ss', (xValue += minute)),//时间。在本例中作为横坐标
                +boxVals[openIdx].toFixed(2),//期货K线图中的开盘价
                +boxVals[3].toFixed(2),//期货K线图中的最高价
                +boxVals[0].toFixed(2),//期货K线图中的最低价
                +boxVals[closeIdx].toFixed(2),//期货K线图中的闭盘价
                +volumn.toFixed(0),//如果对期货不感兴趣，可以认为它无意义。
                getSign(data, i, +boxVals[openIdx], +boxVals[closeIdx], 4) // sign
                ,boxVals[3] * (1000 + Math.random() * 500)//没有实际意义，演示用
                ,boxVals[3] * (100 + Math.random() * 200)//没有实际意义，演示用
            ];
        }
        return data;
        function getSign(data, dataIndex, openVal, closeVal, closeDimIdx) {
            var sign;
            if (openVal > closeVal) {
                sign = -1;
            } else if (openVal < closeVal) {
                sign = 1;
            } else {
                sign =
                    dataIndex > 0
                        ? // If close === open, compare with close of last record
                        data[dataIndex - 1][closeDimIdx] <= closeVal
                            ? 1
                            : -1
                        : // No record of previous, set to be positive
                        1;
            }
            return sign;
        }
    }

    if (option && typeof option === 'object') {
        myChart.setOption(option);
    }
    window.addEventListener('resize', myChart.resize);
</script>

</html>